package com.tianlu.store.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.tianlu.store.common.*;
import com.tianlu.store.dto.StatusCountDTO;
import com.tianlu.store.dto.TeamPerformanceDTO;
import com.tianlu.store.entity.*;
import com.tianlu.store.enums.OrderStatusEnum;
import com.tianlu.store.enums.ProductTypeEnum;
import com.tianlu.store.enums.UserLevelEnum;
import com.tianlu.store.mapper.OrderInfoMapper;
import com.tianlu.store.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author 梁东烂
 * @Desc 订单表(OrderInfo)表服务实现类
 * @Date 2023-04-03 17:06:04
 */
@Slf4j
@Service("orderInfoService")
public class OrderInfoServiceImpl extends MyBaseServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {
    @Resource
    ProductInfoService productInfoService;
    @Resource
    OrderProductService orderProductService;
    @Resource
    OrderAddressService orderAddressService;
    @Resource
    UserInfoService userInfoService;
    @Resource
    ShoppingCarService shoppingCarService;

    /**
     * 保存订单
     *
     * @param orderInfo 订单信息
     * @return boolean
     * @author liangdl
     * @since 2023/4/3 18:15
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(OrderInfo orderInfo) {
        List<OrderProduct> productInfoList = orderInfo.getProductInfoList();
        if (CollUtil.isEmpty(productInfoList)) {
            log.error("订单商品为空！");
            throw new ServiceException(ResultCode.CODE_400, "商品不能为空！");
        }
        OrderAddress orderAddress = orderInfo.getOrderAddress();
        if (Objects.isNull(orderAddress)) {
            log.error("收货地址为空！");
            throw new ServiceException(ResultCode.CODE_400, "收货地址不能为空！");
        }

        // 判断用户余额
        UserInfo userInfo = userInfoService.getById(orderInfo.getUserId());
        if (Objects.isNull(userInfo)) {
            log.error("用户不存在！");
            throw new ServiceException(ResultCode.CODE_400);
        }
        if (userInfo.getScore().compareTo(orderInfo.getAmount()) < 0) {
            throw new ServiceException(ResultCode.CODE_400, "余额不足，请联系管理员充值！");
        }

        List<ProductInfo> updateList = new ArrayList<>();

        List<Long> productIdList = new ArrayList<>();

        // 保存订单商品
        for (OrderProduct orderProduct : productInfoList) {
            productIdList.add(orderProduct.getId());

            // 判断库存
            ProductInfo dbProduct = productInfoService.getById(orderProduct.getId());
            if (Objects.isNull(dbProduct)) {
                log.error("商品不存在！" + orderProduct);
                throw new ServiceException(ResultCode.CODE_400);
            }
            if (dbProduct.getStock() - orderProduct.getQuantity() < 0) {
                throw new ServiceException(ResultCode.CODE_400, "【" + orderProduct.getName() + "】商品库存不足！");
            }
            dbProduct.setStock(dbProduct.getStock() - orderProduct.getQuantity());
            updateList.add(dbProduct);

            orderProduct.setProductId(dbProduct.getId());
            orderProduct.setId(IdGen.snowflakeId());
            orderProduct.setOrderId(orderInfo.getId());
        }
        orderProductService.saveBatch(productInfoList);

        // 保存地址
        orderAddress.setId(IdGen.snowflakeId());
        orderAddress.setOrderId(orderInfo.getId());
        orderAddressService.save(orderAddress);

        // 修改库存
        productInfoService.updateStock(updateList);

        // 修改用户余额
        userInfo.setScore(userInfo.getScore().subtract(orderInfo.getAmount()));
        userInfo.setMsg("下单扣减");

        // 从购物车移除对应的商品
        shoppingCarService.deleteProduct(productIdList, userInfo.getId());

        // 判断是否需要改变用户的等级
        if (!Objects.equals(userInfo.getLevel(), UserLevelEnum.COMPANY.value)) {
            Integer type = orderInfo.getProductInfoList().stream().max(Comparator.comparing(OrderProduct::getType)).get().getType();
            if (Objects.nonNull(type) && type > userInfo.getLevel()) {
                userInfo.setLevel(type);
            }
        }

        // 修改用户信息
        userInfoService.updateById(userInfo);

        // 给上级分佣
        this.divide(userInfo, orderInfo);

        // 保存订单
        orderInfo.setType(1);
        orderInfo.setStatus(OrderStatusEnum.WAIT_SEND.value);
        orderInfo.setPayTime(new Date());
        return super.save(orderInfo);
    }

    /**
     * 给上级分佣
     *
     * @param userInfo  用户信息
     * @param orderInfo 订单信息
     * @author liangdl
     * @since 2023/4/26 17:36
     */
    public void divide(UserInfo userInfo, OrderInfo orderInfo) {
        // 给上级分佣
        String parentIds = userInfo.getParentIds();
        List<UserInfo> parentList = userInfoService.findByIds(parentIds);
        if (CollUtil.isEmpty(parentList)) {
            return;
        }
        Map<Long, UserInfo> parentMap = parentList.stream().collect(Collectors.toMap(BaseEntity::getId, it -> it));
        String[] idArray = parentIds.split(",");

        // 剩余分红
        BigDecimal leave = BigDecimal.valueOf(0.4);
        // 订单金额减去快递费
        BigDecimal orderAmount = orderInfo.getAmount().subtract(BigDecimal.valueOf(12));
        for (int i = idArray.length - 1; i >= 0; i--) {
            UserInfo parent = parentMap.get(Long.parseLong(idArray[i]));
            if (Objects.isNull(parent) || UserLevelEnum.VISITOR.value.equals(parent.getLevel())) {
                continue;
            }

            // 分公司最高分40%
            if (UserLevelEnum.COMPANY.value.equals(parent.getLevel())) {
                BigDecimal multiply = orderAmount.multiply(leave);
                parent.setScore(parent.getScore().add(multiply));
                parent.setMsg("下级分佣");
                userInfoService.updateById(parent);
                break;
            }

            // 代理商最高分30%
            if (UserLevelEnum.AGENT.value.equals(parent.getLevel()) && leave.compareTo(BigDecimal.valueOf(0.4)) == 0) {
                BigDecimal multiply = orderAmount.multiply(BigDecimal.valueOf(0.3));
                parent.setScore(parent.getScore().add(multiply));
                parent.setMsg("下级分佣");
                userInfoService.updateById(parent);
                leave = leave.subtract(BigDecimal.valueOf(0.3));
            }
        }
    }

    /**
     * 修改订单状态
     *
     * @param id     订单id
     * @param status 修改后的状态
     * @return Boolean
     * @author liangdl
     * @since 2023/4/4 11:16
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateStatus(Long id, Integer status) {
        OrderInfo orderInfo = super.getById(id);
        if (Objects.isNull(orderInfo)) {
            throw new ServiceException(ResultCode.CODE_400, "订单不存在！");
        }
        if (OrderStatusEnum.WAIT_TAKE.value.equals(status)) {
            orderInfo.setSendTime(new Date());
        }
        orderInfo.setStatus(status);
        dao.updateById(orderInfo);
        return true;
    }

    /**
     * 退款
     *
     * @param id 订单id
     * @return Boolean
     * @author liangdl
     * @since 2023/4/4 11:16
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean drawback(Long id) {
        OrderInfo orderInfo = super.getById(id);
        if (Objects.isNull(orderInfo)) {
            throw new ServiceException(ResultCode.CODE_400, "订单不存在！");
        }
        UserInfo userInfo = userInfoService.getById(orderInfo.getUserId());
        if (Objects.isNull(userInfo)) {
            log.error("用户不存在！");
            throw new ServiceException(ResultCode.CODE_400);
        }
        // 修改订单状态
        orderInfo.setStatus(OrderStatusEnum.REFUNDED.value);
        dao.updateById(orderInfo);

        // 给用户退款
        userInfo.setScore(userInfo.getScore().add(orderInfo.getAmount()));
        userInfo.setMsg("退款到账");
        userInfoService.updateById(userInfo);

        // 恢复库存
        OrderProduct query = new OrderProduct();
        query.setOrderId(id);
        List<OrderProduct> productList = orderProductService.findList(query);
        productInfoService.resumeStock(productList);

        return true;
    }

    /**
     * 申请退款
     *
     * @param id 订单id
     * @return Boolean
     * @author liangdl
     * @since 2023/4/4 11:16
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean drawbackApplication(Long id) {
        OrderInfo orderInfo = super.getById(id);
        if (Objects.isNull(orderInfo)) {
            throw new ServiceException(ResultCode.CODE_400, "订单不存在！");
        }
        if (OrderStatusEnum.WAIT_SEND.value.equals(orderInfo.getStatus())) {
            // 待发货的直接退款
            this.drawback(id);
        } else if (OrderStatusEnum.WAIT_TAKE.value.equals(orderInfo.getStatus())) {
            // 待收货的等管理员确认退款
            orderInfo.setStatus(OrderStatusEnum.WAIT_REFUND.value);
            super.updateById(orderInfo);
        } else {
            throw new ServiceException(ResultCode.CODE_400, "只有待发货和待收货的订单才能申请退款！");
        }
        return true;
    }

    /**
     * 发货14天后自动确认收货
     *
     * @author liangdl
     * @since 2023/4/14 11:33
     */
    @Override
    public void autoConfirm() {
        List<Long> autoConfirmList = dao.findAutoConfirmList();
        for (Long id : autoConfirmList) {
            this.confirm(id);
        }
    }

    /**
     * 手动确认收货
     *
     * @param id 订单id
     * @author liangdl
     * @since 2023/4/26 17:36
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirm(Long id) {
        OrderInfo orderInfo = super.getById(id);
        if (Objects.isNull(orderInfo)) {
            throw new ServiceException(ResultCode.CODE_400, "订单不存在！");
        }

        // 修改订单状态
        orderInfo.setStatus(OrderStatusEnum.DONE.value);
        super.updateById(orderInfo);
    }

    /**
     * 根据状态统计数量
     *
     * @param userId 用户id
     * @return List<StatusCountDTO>
     */
    @Override
    public List<StatusCountDTO> countByStatus(Long userId) {
        return dao.countByStatus(userId);
    }

    /**
     * 取消退款
     *
     * @param id 订单id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(Long id) {
        OrderInfo orderInfo = super.getById(id);
        if (Objects.isNull(orderInfo)) {
            throw new ServiceException(ResultCode.CODE_400, "订单不存在！");
        }
        orderInfo.setStatus(OrderStatusEnum.WAIT_TAKE.value);
        super.updateById(orderInfo);
    }

    @Override
    public void deleteById(Long id) {
        OrderInfo orderInfo = super.getById(id);
        if (Objects.isNull(orderInfo)) {
            throw new ServiceException(ResultCode.CODE_400, "订单不存在！");
        }
        if (!OrderStatusEnum.DONE.value.equals(orderInfo.getStatus())
                && !OrderStatusEnum.REFUNDED.value.equals(orderInfo.getStatus())) {
            throw new ServiceException(ResultCode.CODE_400, "只有已完成或已退款的订单才能删除！");
        }

        dao.deleteById(id);
    }

    /**
     * 查询团队业绩
     *
     * @param userIdList 用户id
     * @return 业绩总额
     * @author liangdl
     * @since 2023/5/4 11:06
     */
    @Override
    public BigDecimal findTeamPerformance(List<Long> userIdList) {
        return dao.findTeamPerformance(userIdList);
    }

    /**
     * 添加秒杀/免费订单表接口
     *
     * @param orderInfo 订单对象
     * @author liangdl
     * @since 2023/5/6 10:44
     */
    @Override
    public void saveKillOrFree(OrderInfo orderInfo) {
        synchronized (this) {
            List<OrderProduct> productInfoList = orderInfo.getProductInfoList();
            if (CollUtil.isEmpty(productInfoList)) {
                log.error("订单商品为空！");
                throw new ServiceException(ResultCode.CODE_400, "商品不能为空！");
            }
            OrderAddress orderAddress = orderInfo.getOrderAddress();
            if (Objects.isNull(orderAddress)) {
                log.error("收货地址为空！");
                throw new ServiceException(ResultCode.CODE_400, "收货地址不能为空！");
            }

            // 判断用户余额
            UserInfo userInfo = userInfoService.getById(orderInfo.getUserId());
            if (Objects.isNull(userInfo)) {
                log.error("用户不存在！");
                throw new ServiceException(ResultCode.CODE_400);
            }
            if (userInfo.getScore().compareTo(orderInfo.getAmount()) < 0) {
                throw new ServiceException(ResultCode.CODE_400, "余额不足，请联系管理员充值！");
            }

            List<ProductInfo> updateList = new ArrayList<>();

            // 保存订单商品
            for (OrderProduct orderProduct : productInfoList) {
                // 判断库存
                ProductInfo dbProduct = productInfoService.getById(orderProduct.getId());
                if (Objects.isNull(dbProduct)) {
                    log.error("商品不存在！" + orderProduct);
                    throw new ServiceException(ResultCode.CODE_400);
                }
                if (dbProduct.getStock() - orderProduct.getQuantity() < 0) {
                    if (ProductTypeEnum.FREE.value.equals(orderProduct.getType())) {
                        throw new ServiceException(ResultCode.CODE_400, "免费商品已领完，欢迎下次再来");
                    } else {
                        throw new ServiceException(ResultCode.CODE_400, "秒杀已结束，欢迎下次再来");
                    }
                }

                if (userInfo.getFreeFlag() == 1 && ProductTypeEnum.FREE.value.equals(orderProduct.getType())) {
                    throw new ServiceException(ResultCode.CODE_400, "本周已领取过免费商品，请下周再来");
                }

                if (ProductTypeEnum.FREE.value.equals(orderProduct.getType())) {
                    userInfo.setFreeFlag(1);
                }

                dbProduct.setStock(dbProduct.getStock() - orderProduct.getQuantity());
                updateList.add(dbProduct);

                orderProduct.setProductId(dbProduct.getId());
                orderProduct.setId(IdGen.snowflakeId());
                orderProduct.setOrderId(orderInfo.getId());

                orderInfo.setType(ProductTypeEnum.FREE.value.equals(orderProduct.getType()) ? 2 : 3);
            }

            orderProductService.saveBatch(productInfoList);

            // 保存地址
            orderAddress.setId(IdGen.snowflakeId());
            orderAddress.setOrderId(orderInfo.getId());
            orderAddressService.save(orderAddress);

            // 修改库存
            productInfoService.updateStock(updateList);

            // 修改用户余额
            userInfo.setScore(userInfo.getScore().subtract(orderInfo.getAmount()));
            userInfo.setMsg("下单扣减");
            userInfoService.updateById(userInfo);

            // 保存订单
            orderInfo.setStatus(OrderStatusEnum.WAIT_SEND.value);
            orderInfo.setPayTime(new Date());
            super.save(orderInfo);
        }
    }

    /**
     * 按月查询团队业绩
     *
     * @param userIdList 用户id
     * @return 业绩总额
     * @author liangdl
     * @since 2023/5/4 11:06
     */
    @Override
    public List<TeamPerformanceDTO> findPerformanceDetail(List<Long> userIdList) {
        return dao.findPerformanceDetail(userIdList);
    }

}
